//
//  Order.swift
//  ShareCar
//
//  Created by lishuai on 2018/6/22.
//  Copyright © 2018年 changqingkeji. All rights reserved.
//

import Foundation

/// 订单类型
///
/// - time: 分时订单
/// - date: 日租订单
enum OrderType: Int, Codable {
    case preorder = 0
    case time = 1
    case date = 2
}

struct Order {
    
    /// 订单状态
    ///
    /// - reserve: 预定
    /// - cancelNoPay: 取消
    /// - use: 使用中
    /// - returnCar: 确认还车
    /// - pay: 确认支付
    /// - finish: 已完成
    enum Status: Int, Codable {
        case reserve = 1
        case cancelNoPay = 2
        case use = 3
        case returnCar = 4
        case pay = 5
        case finish = 6
    }
    
    struct Preorder: Codable {
        let orderId: String
        let status: Status?
        let forceFlag: Int?
        let orderType: Int?
        
        enum CodingKeys : String, CodingKey {
            case orderId = "order_id"
            case status = "status"
            case forceFlag = "force_flag"
            case orderType = "order_type"
        }
    }
    
    struct Pay: Codable {
        
        /// 订单编号
        let orderId: String
        
        /// 支付串
        let payStr: String
        
        /// 支付状态
        let payStatus: Int?
        
        enum CodingKeys : String, CodingKey {
            case orderId = "order_id"
            case payStr = "pay_str"
            case payStatus = "pay_status"
        }
        
        enum Payment: Int, Codable {
            case aliPay = 1
            case wePay = 2
            case balance = 6
            case ticket = 9999
        }
    }
    
    struct CancelReason: Codable {
        
        struct CancelPriceRule: Codable {
            let time: String
            let unit: String
            let desc: String
        }
        
        struct Reason: Codable {
            let cancelReasonId: String
            let reasonName: String
            
            enum CodingKeys : String, CodingKey {
                case cancelReasonId = "cancel_reason_id"
                case reasonName = "reason_name"
            }
        }
        
        let cancelPriceRule: [CancelPriceRule]
        let cancelReason: [Reason]
        let surplusCancelNum: Int
        
        enum CodingKeys : String, CodingKey {
            case cancelPriceRule = "cancel_price_rule"
            case cancelReason = "cancel_reason"
            case surplusCancelNum = "surplus_cancel_num"
        }
    }
    
    struct ProgressOrder: Codable {
        let orderId: String
        let orderStatus: Status
        let forceFlag: Int?
        let orderType: Int?
        
        enum CodingKeys : String, CodingKey {
            case orderId = "order_id"
            case orderStatus = "status"
            case forceFlag = "force_flag"
            case orderType = "order_type"
        }
    }
    
    struct Detail: Codable {
        
        /// 订单编号
        let orderId: String
        
        /// 车辆ID
        let carId: String
        
        /// 订单状态
        let orderStatus: Status
        
        /// 车型
        let carTypeName: String
        
        /// 车辆图片
        let carImg: String
        
        /// 车辆所在地址
        let carAddress: String
        
        /// 车辆距离
        let carDistance: Int
        
        /// 车牌号
        let carPlateNumber: String
        
        /// 保留时间
        let retentionTime: Int
        
        /// 下单时间
        let orderTime: Int
        
        /// 车辆经度
        let carLng: String
        
        /// 车辆纬度
        let carLat: String
        
        /// 还车位置
        let returnPos: Int
        
        /// 还车地址
        let returnAddress: String
        
        /// 开门时间
        let opendoorTime: Int
        
        /// tbox厂家编号
        let tboxDeviceCode: String
        
        /// 蓝牙名称
        let bluetoothName: String
        
        /// 蓝牙sn
        let bluetoothSn: String
        
        /// 是否有可用的时长包（1：是；0：否）
        let isUseableDurationPackage: Int
        
        /// 订单选择的时长包id
        let durationPackageId: String
        
        /// 时长包名称
        let durationPackageName: String
        
        /// 分时方案id
        let projectTimerentId: String
        
        /// 验车标识 1:需验车 2:不需要验车
        let checkFlag: Int
        
        /// 订单类型（1：分时；2：日租）
        let orderType: Int
        
        /// 预计租期开始时间
        let preStartTime: Int
        
        /// 预计租期结束时间
        let preEndTime: Int
        
        /// 开门是否上传油量照片标识（0：否；1：是）
        let isUploadOil: Int
        
        /// 是否开门标识（0：否；1：是）
        let opendoorFlag: Int
        
        enum CodingKeys : String, CodingKey {
            case orderId = "order_id"
            case carId = "car_id"
            case orderStatus = "order_status"
            case carTypeName = "car_type_name"
            case carImg = "car_img"
            case carAddress = "car_address"
            case carDistance = "car_distance"
            case carPlateNumber = "car_plate_number"
            case retentionTime = "retention_time"
            case orderTime = "order_time"
            case carLng = "car_lng"
            case carLat = "car_lat"
            case returnPos = "return_pos"
            case returnAddress = "return_address"
            case opendoorTime = "opendoor_time"
            case tboxDeviceCode = "tbox_device_code"
            case bluetoothName = "bluetooth_name"
            case bluetoothSn = "bluetooth_sn"
            case isUseableDurationPackage = "is_useable_duration_package"
            case durationPackageId = "duration_package_id"
            case durationPackageName = "duration_package_name"
            case projectTimerentId = "project_timerent_id"
            case checkFlag = "check_flag"
            case orderType = "order_type"
            case preStartTime = "pre_start_time"
            case preEndTime = "pre_end_time"
            case isUploadOil = "is_upload_oil"
            case opendoorFlag = "opendoor_flag"
        }
    }
    
    struct GasList: Codable {
        
        struct Gas: Codable {
            
            let gasId: String
            let gasName: String
            
            enum CodingKeys : String, CodingKey {
                case gasId = "gas_id"
                case gasName = "gas_name"
            }
        }
        
        enum CodingKeys : String, CodingKey {
            case gasList = "gas_list"
        }
        
        let gasList: [Gas]
    }
    
    struct RecommendReturnList: Codable {
        
        enum SignType: Int, Codable {
            case unsigned     = 1
            case signed   = 2
            case signedUn   = 3
        }
    
        struct Parking: Codable {
            let parkingLotId: String
            let carNum: Int
            let parkingLotLng: String
            let parkingLotLat: String
            let parkingLotDistance: Float
            let parkName: String
            let spaceNum: String
            let signType: SignType
            let fenceFlag: Int
            let radius: String
            let lngLats: [[String]]
    
            enum CodingKeys : String, CodingKey {
                case parkingLotId = "parking_lot_id"
                case carNum = "car_num"
                case parkingLotLng = "parking_lot_lng"
                case parkingLotLat = "parking_lot_lat"
                case parkingLotDistance = "parking_lot_distance"
                case parkName = "park_name"
                case spaceNum = "space_num"
                case signType = "sign_type"
                case fenceFlag = "fence_flag"
                case radius = "radius"
                case lngLats = "lng_lat"
            }
        }
        
        let parkingLotList: [Parking]
        
        enum CodingKeys : String, CodingKey {
            case parkingLotList = "parking_lot_list"
        }
    }
    
    struct ReturnCar: Codable {
        
        enum LocType: Int, Codable {
            case charge = 1
            case free = 2
        }
        
        let type: LocType
        let parkingFee: Int
        let distance: Int
        let amount: Int
        
        enum CodingKeys : String, CodingKey {
            case type = "type"
            case parkingFee = "parking_fee"
            case distance = "distance"
            case amount = "amount"
        }
    }
    
    struct ConfirmReturnCar: Codable {
        let orderId: String
        let accStatus: Int
        let doorStatus: Int
        let lightStatus: Int
        let gearStatus: Int
        
        enum CodingKeys : String, CodingKey {
            case orderId = "order_id"
            case accStatus = "acc_status"
            case doorStatus = "door_status"
            case lightStatus = "light_status"
            case gearStatus = "gear_status"
        }
    }
    
    struct ReturnDetail: Codable {
        
        struct CouponList: Codable {
            let couponId: String
            let couponName: String
            
            enum CodingKeys : String, CodingKey {
                case couponId = "coupon_id"
                case couponName = "coupon_name"
            }
        }
        
        struct DurationPackageData: Codable {
            let isUseableDurationPackage: Int
            let durationPackageId: String
            let durationPackageName: String
            let projectTimerentId: String
            
            enum CodingKeys : String, CodingKey {
                case isUseableDurationPackage = "is_useable_duration_package"
                case durationPackageId = "duration_package_id"
                case durationPackageName = "duration_package_name"
                case projectTimerentId = "project_timerent_id"
            }
        }
        
        let stepFee: String
        let longFee: String
        let mileageFee: String
        let overtimeFee: String
        let returnAttachFee: String
        let noDeductibles: String
        let benefitFee: String
        let miMoney: String
        let couponUseable: Int
        let payableFee: String
        let totalFee: String
        let orderId: String
        let couponList: [CouponList]
        let couponOrderFee: String
        let payableFlag: Int
        let balanceFlag: Int
        let durationPackageData: DurationPackageData
        
        
        enum CodingKeys : String, CodingKey {
            case stepFee = "step_fee"
            case longFee = "long_fee"
            case mileageFee = "mileage_fee"
            case overtimeFee = "overtime_fee"
            case returnAttachFee = "return_attach_fee"
            case noDeductibles = "no_deductibles"
            case benefitFee = "benefit_fee"
            case miMoney = "mi_money"
            case couponUseable = "coupon_useable"
            case payableFee = "payable_fee"
            case totalFee = "total_fee"
            case orderId = "order_id"
            case couponList = "coupon_list"
            case couponOrderFee = "coupon_order_fee"
            case payableFlag = "payable_flag"
            case balanceFlag = "balance_flag"
            case durationPackageData = "duration_package_data"
        }
    }
    
    struct CancelPreorder: Codable {
        let payStatus: Int
        let orderId: String
        let payFee: String?
        let appointDuration: Int?
        
        enum CodingKeys : String, CodingKey {
            case payStatus = "pay_status"
            case orderId = "order_id"
            case payFee = "pay_fee"
            case appointDuration = "appoint_duration"
        }
    }
    
    struct AddOil: Codable {
        let orderOilId: String
        
        enum CodingKeys : String, CodingKey {
            case orderOilId = "order_oil_id"
        }
    }
    
    struct CancelOrderPay: Codable {
        let orderId: String
        let payStr: String
        
        enum CodingKeys : String, CodingKey {
            case orderId = "order_id"
            case payStr = "pay_str"
        }
    }
    
    struct PaySwith: Codable {
        let list : [Method]
        
        struct Method: Codable {
            let payMethod: Pay.Payment
            
            enum CodingKeys : String, CodingKey {
                case payMethod = "pay_method"
            }
        }
    }
    
    struct PayCoupon: Codable {
        let list: [Coupon]
        
        struct Coupon: Codable {
            let couponId: String
            let couponName: String
            let superpositionFlag: Int
            let eventType: Int
            let expireTime: String
            let brief: String
            
            enum CodingKeys : String, CodingKey {
                case couponId = "coupon_id"
                case couponName = "coupon_name"
                case superpositionFlag = "superposition_flag"
                case eventType = "event_type"
                case expireTime = "expire_time"
                case brief = "brief"
            }
        }
    }
    
    struct CancelAmount: Codable {
        let payableMoney: String
        let appointDuration: Int
        let balanceFlag: Int
        
        enum CodingKeys : String, CodingKey {
            case payableMoney = "payable_money"
            case appointDuration = "appoint_duration"
            case balanceFlag = "balance_flag"
        }
    }
    
    struct DurationPackageList: Codable {
        
        struct Item: Codable {
            let durationPackageId: String
            let packageName: String
            let hour: Int
            let standardPrice: String
            let monthPrice: String
            let yearPrice: String
            
            enum CodingKeys : String, CodingKey {
                case durationPackageId = "duration_package_id"
                case packageName = "package_name"
                case hour = "hour"
                case standardPrice = "standard_price"
                case monthPrice = "month_price"
                case yearPrice = "year_price"
            }
        }
        
        let list: [Item]
    }
    
    struct DailyFeeDetail: Codable {
        let orderId: String
        let ordersn: String
        let payableAmount: String
        let isNeedPay: Int
        let isOilPay: Int
        let balanceFlag: Int
        let totalAmountData: TotalAmountData
        let paidAmountData: PaidAmountData
        
        enum CodingKeys: String, CodingKey {
            case orderId = "order_id"
            case ordersn = "order_sn"
            case payableAmount = "payable_amount"
            case isNeedPay = "is_need_pay"
            case isOilPay = "is_oil_pay"
            case balanceFlag = "balance_flag"
            case totalAmountData = "total_amount_data"
            case paidAmountData = "paid_amount_data"
        }
        
        struct TotalAmountData: Codable {
            let totalAmount: String
            let rentAmount: String
            let noDeductibles: String
            let prepareAmount: String
            let returnAmount: String
            let oilAmount: String
            
            enum CodingKeys: String, CodingKey {
                case totalAmount = "total_amount"
                case rentAmount = "rent_amount"
                case noDeductibles = "no_deductibles"
                case prepareAmount = "prepare_amount"
                case returnAmount = "return_amount"
                case oilAmount = "oil_amount"
            }
        }
        
        struct PaidAmountData: Codable {
            let prepayAmount: String
            let rentAmount: String
            let prepareAmount: String
            let noDeductibles: String
            
            enum CodingKeys: String, CodingKey {
                case prepayAmount = "prepay_amount"
                case rentAmount = "rent_amount"
                case prepareAmount = "prepare_amount"
                case noDeductibles = "no_deductibles"
            }
        }
        
    }
    
    struct QueryPrepayDetail: Codable {
        let orderId: String
        let orderSn: String
        let preStartTime: Int
        let preEndTime: Int
        let preTotalAmount: String
        let preDayAmount: String
        let prePrepareAmount: String
        let preNodeductAmount: String
        let orderTime: Int
        let balanceFlag: Int
        
        enum CodingKeys : String, CodingKey {
            case orderId = "order_id"
            case orderSn = "order_sn"
            case preStartTime = "pre_start_time"
            case preEndTime = "pre_end_time"
            case preTotalAmount = "pre_total_amount"
            case preDayAmount = "pre_day_amount"
            case prePrepareAmount = "pre_prepare_amount"
            case preNodeductAmount = "pre_nodeduct_amount"
            case orderTime = "order_time"
            case balanceFlag = "balance_flag"
        }
    }
    
    struct PrepayPay: Codable {
        let orderId: String
        let payStr: String
        let payStatus: Int
        
        enum CodingKeys : String, CodingKey {
            case orderId = "order_id"
            case payStr = "pay_str"
            case payStatus = "pay_status"
        }
    }
    
    struct DailyOrderDetail: Codable {
        let orderId: String
        let isNeedPay: Int
        let payStatus: Int
        let payableAmount: String
        let beginTime: Int
        let endTime: Int
        let isOilPay: String
        
        struct TotalAmountData: Codable {
            let realRentDays: String
            let totalAmount: String
            let rentAmount: String
            let noDeductibles: String
            let prepareAmount: String
            let returnAmount: String
            let oilAmount: String
            
            enum CodingKeys : String, CodingKey {
                case realRentDays = "real_rent_days"
                case totalAmount = "total_amount"
                case rentAmount = "rent_amount"
                case noDeductibles = "no_deductibles"
                case prepareAmount = "prepare_amount"
                case returnAmount = "return_amount"
                case oilAmount = "oil_amount"
            }
        }
        
        let totalAmountData: TotalAmountData
        
        struct PaidAmountData: Codable {
            let rentDays: Int
            let prepayAmount: String
            let rentAmount: String
            let prepareAmount: String
            let noDeductibles: String
            
            enum CodingKeys : String, CodingKey {
                case rentDays = "rent_days"
                case prepayAmount = "prepay_amount"
                case rentAmount = "rent_amount"
                case prepareAmount = "prepare_amount"
                case noDeductibles = "no_deductibles"
            }
        }
        
        let paidAmountData: PaidAmountData
        
        let orderSn: String
        let imagePath: String
        let plateNumber: String
        let carTypeName: String
        
        enum CodingKeys : String, CodingKey {
            case orderId = "order_id"
            case isNeedPay = "is_need_pay"
            case payStatus = "pay_status"
            case payableAmount = "payable_amount"
            case beginTime = "begin_time"
            case endTime = "end_time"
            case isOilPay = "is_oil_pay"
            
            case totalAmountData = "total_amount_data"
            case paidAmountData = "paid_amount_data"
            
            case orderSn = "order_sn"
            case imagePath = "image_path"
            case plateNumber = "plate_number"
            case carTypeName = "car_type_name"
        }
    }
}

extension Order {
    
    /// 预定
    ///
    /// - Parameters:
    ///   - carId: 车辆id
    ///   - noDeductibles: 不计免赔（1：否；2：是）
    ///   - appointDuration: 加时时长
    ///   - orderAddress: 下单地址
    ///   - location: 用户所在经纬度
    ///   - durationPackageId: 选择的时长包id
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func preorder(carId: String,
                         noDeductibles: Int,
                         appointDuration: Int = 0,
                         orderAddress: String,
                         location: CLLocationCoordinate2D?,
                         rentDays: Int,
                         preorderType: Int,
                         durationPackageId: String?,
                         success: @escaping (Preorder?) -> (),
                         failure: @escaping (Message, Preorder?) -> ()) {
        
        var parameters = [String: Any]()
        if preorderType == 1 {
            
            parameters = ["car_id": carId,
                          "no_deductibles": noDeductibles,
                          "appoint_duration": appointDuration,
                          "order_address": orderAddress,
                          "preorder_type":preorderType
            ]
            
        } else if preorderType == 2 {
            parameters = ["car_id": carId,
                          "no_deductibles": noDeductibles,
                          "rent_days": rentDays,
                          "order_address": orderAddress,
                          "preorder_type":preorderType
            ]
        }

        
        if let loc = location {
            parameters["lng"] = String(loc.longitude)
            parameters["lat"] = String(loc.latitude)
        }
        
        if let d = durationPackageId {
            parameters["duration_package_id"] = d
        }
        
        Base<Preorder>.request(URIString: "user/preorder", parameters: parameters, success: { data in
            success(data)
        }) { error, data in
            failure(error, data)
        }
    }
    
    /// 取消预定
    ///
    /// - Parameters:
    ///   - orderId: 订单ID
    ///   - reason: 取消原因
    ///   - location: 用户所在经纬度
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func cancelPreorder(orderId: String,
                               reason: String,
                               location: CLLocationCoordinate2D?,
                               success: @escaping (CancelPreorder?) -> (),
                               failure: @escaping (Message) -> ()) {
        
        var parameters: [String: Any] = ["order_id": orderId,
                                         "reason": reason]
        
        if let loc = location {
            parameters["lng"] = String(loc.longitude)
            parameters["lat"] = String(loc.latitude)
        }
        
        Base<CancelPreorder>.request(URIString: "user/cancel_preorder", parameters: parameters, success: { data in
            success(data)
        }) { error, data in
            failure(error)
        }
    }
    
    /// 支付
    ///
    /// - Parameters:
    ///   - orderId: 订单ID
    ///   - payment: 支付方式（1：支付宝；2：微信；4：Apple Pay）
    ///   - couponId: 优惠券ID
    ///   - location: 用户所在经纬度
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func pay(orderId: String,
                    payment: Pay.Payment?,
                    couponId: String?,
                    location: CLLocationCoordinate2D?,
                    success: @escaping (Pay?) -> (),
                    failure: @escaping (Message) -> ()) {
        
        var parameters: [String: Any] = ["order_id": orderId]
        
        if let couponId = couponId {
            parameters["coupon_id"] = couponId
        }
        
        if let payment = payment {
            parameters["payment"] = payment.rawValue
        }
        
        if let loc = location {
            parameters["lng"] = String(loc.longitude)
            parameters["lat"] = String(loc.latitude)
        }
        
        Base<Pay>.request(URIString: "user/pay", parameters: parameters, success: { data in
            success(data)
        }) { error, data in
            failure(error)
        }
    }
    
    /// 欠款订单支付
    ///
    /// - Parameters:
    ///   - orderId: 订单ID
    ///   - payment: 支付方式（1：支付宝；2：微信）
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func payUnfinishOrder(orderId: String,
                                 payment: Int,
                                 success: @escaping (Pay?) -> (),
                                 failure: @escaping (Message) -> ()) {
        
        let parameters: [String: Any] = ["order_id": orderId,
                                         "payment": payment]
        
        
        Base<Pay>.request(URIString: "user/debt_order_pay", parameters: parameters, success: { data in
            success(data)
        }) { error, data in
            failure(error)
        }
    }
    
    /// 欠款订单支付----我的欠款
    ///
    /// - Parameters:
    ///   - orderId: 订单ID
    ///   - payment: 支付方式（1：支付宝；2：微信）
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func payOrderDebt(receipt_sn: String,
                                 payment: Int,
                                 success: @escaping (User.PayInfo?) -> (),
                                 failure: @escaping (Message) -> ()) {
        
        let parameters: [String: Any] = ["receipt_sn": receipt_sn,
                                         "payment": payment]
        
        Base<User.PayInfo>.request(URIString: "user/pay_receipt", parameters: parameters, success: { data in
            success(data)
        }) { error, data in
            failure(error)
        }
    }


    /// 获取取消原因
    ///
    /// - Parameters:
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func cancelReason(success: @escaping (CancelReason?) -> (),
                             failure: @escaping (Message) -> ()) {
        Base<CancelReason>.request(URIString: "user/get_cancel_reason", success: { data in
            success(data)
        }) { error, data in
            failure(error)
        }
    }
    
    /// 获取用户进行中订单
    ///
    /// - Parameters:
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func progressOrder(success: @escaping (ProgressOrder?) -> (),
                              failure: @escaping (Message) -> ()) {
        let progressOrderKey = "com.jz.get_user_progress_order"
        Base<ProgressOrder>.request(URIString: "user/get_user_progress_order", success: { data in
            success(data)
            
            if let d = data {
                do {
                    let json = try JSONEncoder().encode(d)
                    UserDefaults.standard.setValue(json, forKey: progressOrderKey)
                } catch {
                    p(error)
                }
            }
        }) { msg, _ in
            if msg.code == 0 {
                do {
                    if let data = UserDefaults.standard.value(forKey: progressOrderKey) as? Data {
                        let rs = try JSONDecoder().decode(ProgressOrder.self, from: data)
                        success(rs)
                    } else {
                        failure(msg)
                    }
                } catch {
                    failure(msg)
                }
            } else {
                failure(msg)
            }
        }
    }
    
    /// 获取订单详情
    ///
    /// - Parameters:
    ///   - orderId: 订单ID
    ///   - location: 用户所在经纬度
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func detail(orderId: String,
                       location: CLLocationCoordinate2D?,
                       success: @escaping (Detail?) -> (),
                       failure: @escaping (Message) -> ()) {
        let orderDetailKey = "com.jz.get_progress_order_detail"
        
        var parameters: [String: Any] = ["order_id": orderId]
        
        if let loc = location {
            parameters["lng"] = String(loc.longitude)
            parameters["lat"] = String(loc.latitude)
        }
        
        Base<Detail>.request(URIString: "user/get_progress_order_detail", parameters: parameters, success: { data in
            success(data)
            
            if let d = data {
                do {
                    let json = try JSONEncoder().encode(d)
                    UserDefaults.standard.setValue(json, forKey: orderDetailKey)
                } catch {
                    p(error)
                }
            }
        }) { msg, _ in
            if msg.code == 0 {
                do {
                    if let data = UserDefaults.standard.value(forKey: orderDetailKey) as? Data {
                        let rs = try JSONDecoder().decode(Detail.self, from: data)
                        success(rs)
                    } else {
                        failure(msg)
                    }
                } catch {
                    failure(msg)
                }
            } else {
                failure(msg)
            }
        }
    }
    
    /// 继续加时
    ///
    /// - Parameters:
    ///   - orderId: 订单ID
    ///   - location: 用户所在经纬度
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func addTime(orderId: String,
                        location: CLLocationCoordinate2D?,
                        success: @escaping ([String: String]?) -> (),
                        failure: @escaping (Message) -> ()) {
        
        var parameters: [String: Any] = ["order_id": orderId]
        
        if let loc = location {
            parameters["lng"] = String(loc.longitude)
            parameters["lat"] = String(loc.latitude)
        }
        
        Base<[String: String]>.request(URIString: "user/add_time", parameters: parameters, success: { data in
            success(data)
        }) { error, data in
            failure(error)
        }
    }
    
    /// 开门
    ///
    /// - Parameters:
    ///   - orderId: 订单ID
    ///   - faceImg: 面部图片
    ///   - location: 用户所在经纬度
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func openDoor(orderId: String,
                         faceImg: Data? = nil,
                         location: CLLocationCoordinate2D?,
                         success: @escaping () -> (),
                         failure: @escaping (Message) -> ()) {
        
        var parameters: [String: Any] = ["order_id": orderId]
        
        if let loc = location {
            parameters["lng"] = String(loc.longitude)
            parameters["lat"] = String(loc.latitude)
        }
        
        if let image = faceImg {
            let imgFile = HTTPRequest.File(data: image, name: "face_img", fileName: "face.png", mimeType: "image/png")
            
            Base<String>.upload(URIString: "user/open_door", files: [imgFile], parameters: parameters, success: { data in
                success()
            }) { error, data in
                failure(error)
            }
        } else {
            Base<String>.request(URIString: "user/open_door", parameters: parameters, success: { data in
                success()
            }) { error, data in
                failure(error)
            }
        }
    }
    
    /// 获取加油商列表
    ///
    /// - Parameters:
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func gasList(success: @escaping ([GasList.Gas]?) -> (),
                        failure: @escaping (Message) -> ()) {
        Base<GasList>.request(URIString: "user/get_gas_list", success: { data in
            success(data?.gasList)
        }) { error, data in
            failure(error)
        }
    }
    
    /// 加油
    ///
    /// - Parameters:
    ///   - orderId: 订单ID
    ///   - gasId: 加油站ID
    ///   - oilMoney: 加油金额
    ///   - location: 用户所在经纬度
    ///   - rise: 加油量 单位升
    ///   - oilImagePath: 加油图片
    ///   - billImagePath: 加油小票图片
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func addOil(orderId: String,
                       gasId: String,
                       oilMoney: Float,
                       location: CLLocationCoordinate2D?,
                       rise: Float,
                       oilImagePath: String,
                       billImagePath: String,
                       success: @escaping () -> (),
                       failure: @escaping (Message) -> ()) {
        
        var parameters: [String: Any] = ["order_id": orderId,
                                         "gas_id": gasId,
                                         "oil_money": oilMoney,
                                         "rise": rise,
                                         "oil_image_path": oilImagePath,
                                         "bill_image_path": billImagePath]
        
        if let loc = location {
            parameters["lng"] = String(loc.longitude)
            parameters["lat"] = String(loc.latitude)
        }
        
        Base<AddOil>.request(URIString: "user/add_oil", parameters: parameters, success: { data in
            success()
        }) { error, data in
            failure(error)
        }
    }
    
    /// 推荐还车点列表
    ///
    /// - Parameters:
    ///   - location: 经纬度
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func recommendReturnList(location: CLLocationCoordinate2D,
                                    success: @escaping ([RecommendReturnList.Parking]?) -> (),
                                    failure: @escaping (Message) -> ()) {
        
        let parameters = ["lng": String(location.longitude),
                          "lat": String(location.latitude)]
        
        Base<RecommendReturnList>.request(URIString: "user/get_recommend_return_list", parameters: parameters, success: { data in
            success(data?.parkingLotList)
        }) { error, data in
            failure(error)
        }
    }
    
    /// 还车
    ///
    /// - Parameters:
    ///   - orderId: 订单号
    ///   - location: 经纬度
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func returnCar(orderId: String,
                          location: CLLocationCoordinate2D,
                          success: @escaping (ReturnCar?) -> (),
                          failure: @escaping (Message) -> ()) {
        
        let parameters: [String: Any] = ["order_id": orderId,
                                         "lng": String(location.longitude),
                                         "lat": String(location.latitude)]
        
        Base<ReturnCar>.request(URIString: "user/return_car", parameters: parameters, success: { data in
            success(data)
        }) { error, data in
            failure(error)
        }
    }
    
    /// 确认还车
    ///
    /// - Parameters:
    ///   - orderId: 订单ID
    ///   - parkingAddress: 停车场地址
    ///   - parkingPos: 停车位置（1：地面；2：地下）
    ///   - remark: 备注
    ///   - location: 经纬度
    ///   - bluetoothType: 1是蓝牙，2网络
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func confirmReturnCar(orderId: String,
                                 parkingAddress: String,
                                 parkingPos: String,
                                 remark: String?,
                                 location: CLLocationCoordinate2D,
                                 bluetoothType: Int,
                                 success: @escaping (ConfirmReturnCar?) -> (),
                                 failure: @escaping (Message, ConfirmReturnCar?) -> ()) {
        
        var parameters: [String: Any] = ["order_id": orderId,
                                         "parking_address": parkingAddress,
                                         "parking_pos": parkingPos,
                                         "bluetooth_type": bluetoothType,
                                         "lng": String(location.longitude),
                                         "lat": String(location.latitude)]
        
        if let remark = remark {
            parameters["remark"] = remark
        }
     
        Base<ConfirmReturnCar>.request(URIString: "user/confirm_return_car", parameters: parameters, success: { data in
            success(data)
        }) { error, data in
            failure(error, data)
        }
    }
    
    /// 还车费用明细
    ///
    /// - Parameters:
    ///   - orderId: 订单ID
    ///   - couponId: 优惠券ID
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func returnDetail(orderId: String,
                             couponId: String? = nil,
                             success: @escaping (ReturnDetail?) -> (),
                             failure: @escaping (Message) -> ()) {
        
        var parameters: [String: Any] = ["order_id": orderId]
        
        if let couponId = couponId {
            parameters["coupon_id"] = couponId
        }
        
        Base<ReturnDetail>.request(URIString: "user/get_return_detail", parameters: parameters, success: { data in
            success(data)
        }) { error, data in
            failure(error)
        }
    }
    
    /// 鸣笛
    ///
    /// - Parameters:
    ///   - orderId: 订单ID
    ///   - location: 经纬度
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func whistle(orderId: String,
                        location: CLLocationCoordinate2D?,
                        success: @escaping () -> (),
                        failure: @escaping (Message) -> ()) {
        
        var parameters: [String: Any] = ["order_id": orderId]
        
        if let loc = location {
            parameters["lng"] = String(loc.longitude)
            parameters["lat"] = String(loc.latitude)
        }

        Base<String>.request(URIString: "user/whistle", parameters: parameters, success: { data in
            success()
        }) { error, data in
            failure(error)
        }
    }
    
    /// 双闪
    ///
    /// - Parameters:
    ///   - orderId: 订单ID
    ///   - location: 经纬度
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func doubleFlicker(orderId: String,
                              location: CLLocationCoordinate2D?,
                              success: @escaping () -> (),
                              failure: @escaping (Message) -> ()) {
        
        var parameters: [String: Any] = ["order_id": orderId]
        
        if let loc = location {
            parameters["lng"] = String(loc.longitude)
            parameters["lat"] = String(loc.latitude)
        }
        
        Base<String>.request(URIString: "user/double_flicker", parameters: parameters, success: { data in
            success()
        }) { error, data in
            failure(error)
        }
    }
    
    /// 获取支付方法
    ///
    /// - Parameters:
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func paySwith(success: @escaping ([PaySwith.Method]?) -> (),
                         failure: @escaping (Message) -> ()) {
        
        Base<PaySwith>.request(URIString: "user/get_pay_swith", success: { data in
            success(data?.list)
        }) { error, data in
            failure(error)
        }
    }
    
    /// 取消预定支付
    ///
    /// - Parameters:
    ///   - orderId: 订单ID
    ///   - payment: 支付方式
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func cancelOrderPay(orderId: String,
                               payment: Pay.Payment,
                               success: @escaping (CancelOrderPay?) -> (),
                               failure: @escaping (Message) -> ()) {
        
        let parameters: [String: Any] = ["order_id": orderId,
                                         "payment": payment.rawValue]
        
        Base<CancelOrderPay>.request(URIString: "user/cancel_order_pay", parameters: parameters, success: { data in
            success(data)
        }) { error, data in
            failure(error)
        }
    }
    
    /// 锁门
    ///
    /// - Parameters:
    ///   - orderId: 订单id
    ///   - location: 经纬度
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func lockDoor(orderId: String,
                         location: CLLocationCoordinate2D?,
                         success: @escaping () -> (),
                         failure: @escaping (Message) -> ()) {
        
        var parameters: [String: Any] = ["order_id": orderId]
        
        if let loc = location {
            parameters["lng"] = String(loc.longitude)
            parameters["lat"] = String(loc.latitude)
        }
        
        Base<String>.request(URIString: "user/lock_door", parameters: parameters, success: { data in
            success()
        }) { error, data in
            failure(error)
        }
    }
    
    /// 获取不可叠加优惠券列表
    ///
    /// - Parameters:
    ///   - money: 金额
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func payCoupon(money: String,
                          success: @escaping ([PayCoupon.Coupon]?) -> (),
                          failure: @escaping (Message) -> ()) {
        
        let parameters: [String: Any] = ["money": money]
        
        Base<PayCoupon>.request(URIString: "user/get_superposition_coupon_list", parameters: parameters, success: { data in
            success(data?.list)
        }) { error, data in
            failure(error)
        }
    }
    
    /// 获取已取消订单金额详情
    ///
    /// - Parameters:
    ///   - orderId: 订单号
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func cancelAmount(orderId: String,
                             success: @escaping (CancelAmount?) -> (),
                             failure: @escaping (Message) -> ()) {
        
        let parameters: [String: Any] = ["order_id": orderId]
        
        Base<CancelAmount>.request(URIString: "user/get_cancel_amount", parameters: parameters, success: { data in
            success(data)
        }) { error, data in
            failure(error)
        }
    }
    
    
    /// 强制结单
    ///
    /// - Parameters:
    ///   - orderId: 订单id
    ///   - descInfo: 描述信息
    ///   - imagePath: 图片数组
    ///   - lat: 经度
    ///   - lon: 维度
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func coerceEndOrder(orderId: String,
                               descInfo: String,
                               imagePath:[String]?,
                               lat: Double?,
                               lon: Double?,
                               boardImage:String?,
                               oilStatus: Int? = 0,
                               success: @escaping () -> (),
                               failure: @escaping (Message) -> ()) {
        
        var parameters: [String: Any] = [
            "order_id": orderId,
            "problem_desc":descInfo.trimmingCharacters(in: .whitespaces)
        ]
        
        if let oilStatus = oilStatus {
            parameters["oil_status"] = oilStatus
        } else {
            parameters["oil_status"] = 0
        }
        
        if let boardImage = boardImage {
            parameters["board_img"] = boardImage
        }
        
        if let lat = lat, let lon = lon {
            parameters["lng"] = lon
            parameters["lat"] = lat
        }
        
        if let imagePath = imagePath {
            parameters["problem_img"] = imagePath
        }
        
        Base<CancelAmount>.request(URIString: "user/force_finish_order", parameters: parameters, success: { data in
            success()
        }) { error, data in
            failure(error)
        }
    }

    
    /// 时长包列表
    ///
    /// - Parameters:
    ///   - projectTimerentId: 分时方案id
    ///   - sourceFlag: 来源标识（1：预定；2：进行中订单；3：支付页面）
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func durationPackageList(projectTimerentId: String,
                                    sourceFlag: Int,
                                    success: @escaping ([DurationPackageList.Item]?) -> (),
                                    failure: @escaping (Message) -> ()) {
        
        let parameters: [String: Any] = ["project_timerent_id": projectTimerentId,
                                         "source_flag":sourceFlag]
        
        Base<DurationPackageList>.request(URIString: "user/duration_package_list", parameters: parameters, success: { data in
            success(data?.list)
        }) { error, data in
            failure(error)
        }
    }
    
    /// 保存时长包
    ///
    /// - Parameters:
    ///   - orderId: 订单ID
    ///   - durationPackageId: 时长包id(不传或传空字符串时取消时长包)
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func saveDurationPackage(orderId: String,
                                    durationPackageId: String?,
                                    success: @escaping () -> (),
                                    failure: @escaping (Message) -> ()) {
        
        var parameters: [String: Any] = ["order_id": orderId]
        
        if let d = durationPackageId {
            parameters["duration_package_id"] = d
        }
        
        Base<String>.request(URIString: "user/save_duration_package", parameters: parameters, success: { _ in
            success()
        }) { error, data in
            failure(error)
        }
    }
    
    
    /// 上传验车照片
    ///
    /// - Parameters:
    ///   - orderId: 订单ID
    ///   - checkImage: 图片数组
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func checkCar(orderId: String,
                         checkImage: [String: String],
                         success: @escaping () -> (),
                         failure: @escaping (Message) -> ()) {
        let parameters: [String: Any] = ["order_id": orderId,
                                         "check_image": checkImage]
        Base<String>.request(URIString: "user/check_car", parameters: parameters, success: { _ in
            success()
        }) { error, data in
            failure(error)
        }
    }
    
    
    /// 获取日租订单预付费明细
    ///
    /// - Parameters:
    ///   - orderId: 订单ID
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func queryPrepayDetail(orderId: String,
                         success: @escaping (QueryPrepayDetail?) -> (),
                         failure: @escaping (Message) -> ()) {
        
        let parameters: [String: Any] = ["order_id": orderId]
        
        Base<QueryPrepayDetail>.request(URIString: "user/query_prepay_detail", parameters: parameters, success: { data in
            success(data)
        }) { error, data in
            failure(error)
        }
    }
    
    
    /// 日租订单预付费支付
    ///
    /// - Parameters:
    ///   - orderSn: 订单号
    ///   - payment: 支付方式
    ///   - location: 经纬度
    ///   - couponSn: 预售券码
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func prepayPay(orderSn: String,
                          payment: Pay.Payment? = nil,
                          location: CLLocationCoordinate2D? = nil,
                          couponSn: String?,
                          success: @escaping (PrepayPay?) -> (),
                          failure: @escaping (Message) -> ()) {
        
        var parameters: [String: Any] = ["order_sn": orderSn]
        
        if let p = payment {
            parameters["payment"] = p.rawValue
        }
        
        if let loc = location {
            parameters["lng"] = String(loc.longitude)
            parameters["lat"] = String(loc.latitude)
        }

        if let sn = couponSn {
            parameters["coupon_sn"] = sn
        }
        
        Base<PrepayPay>.request(URIString: "user/prepay_pay", parameters: parameters, success: { data in
            success(data)
        }) { error, data in
            failure(error)
        }
    }
    
    
    /// 直接还车
    ///
    /// - Parameters:
    ///   - orderId: 订单号
    ///   - location: 经纬度
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func straightReturnCar(orderId: String,
                                  location: CLLocationCoordinate2D,
                                  success: @escaping () -> (),
                                  failure: @escaping (Message) -> ()) {
        
        let parameters: [String: Any] = ["order_id": orderId,
                                         "lng": String(location.longitude),
                                         "lat": String(location.latitude)]
        
        Base<String>.request(URIString: "user/straight_return_car", parameters: parameters, success: { _ in
            success()
        }) { error, data in
            failure(error)
        }
    }
    
    /// 开门上传油量照片
    ///
    /// - Parameters:
    ///   - orderId: 订单ID
    ///   - boardImg: 仪表盘照片
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func openDoorUploadBoardImg(orderId: String,
                                       boardImg: String,
                                       success: @escaping () -> (),
                                       failure: @escaping (Message) -> ()) {
        
        let parameters: [String: Any] = ["order_id": orderId,
                                         "board_img": boardImg]
        
        Base<String>.request(URIString: "user/opendoor_upload_board_img", parameters: parameters, success: { _ in
            success()
        }) { error, data in
            failure(error)
        }
    }
    
    /// 确认油况
    ///
    /// - Parameters:
    ///   - orderId: 订单ID
    ///   - boardImg: 仪表盘图片
    ///   - oilStatus: 油量刻度（0-16）
    ///   - location: 经纬度
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func confirmOil(orderId: String,
                           boardImg: String,
                           oilStatus: Int,
                           location: CLLocationCoordinate2D?,
                           success: @escaping () -> (),
                           failure: @escaping (Message) -> ()) {
        
        var parameters: [String: Any] = ["order_id": orderId,
                                         "board_img": boardImg,
                                         "oil_status": oilStatus]
        
        if let loc = location {
            parameters["lng"] = String(loc.longitude)
            parameters["lat"] = String(loc.latitude)
        }
        
        Base<String>.request(URIString: "user/confirm_oil", parameters: parameters, success: { _ in
            success()
        }) { error, data in
            failure(error)
        }
    }
    
    /// 获取日租订单详情
    ///
    /// - Parameters:
    ///   - orderId: 订单ID
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func dailyOrderDetail(orderId: String,
                                 success: @escaping (DailyOrderDetail?) -> (),
                                 failure: @escaping (Message) -> ()) {
        
        let parameters: [String: Any] = ["order_id": orderId]
        
        Base<DailyOrderDetail>.request(URIString: "user/query_daily_order_detail", parameters: parameters, success: { data in
            success(data)
        }) { error, data in
            failure(error)
        }
    }
    
    /// 获取日租订单费用明细
    ///
    /// - Parameters:
    ///   - orderId: 订单ID
    ///   - success: 成功回调
    ///   - failure: 失败回调
    static func dailyFeeDetail(orderId: String,
                                 success: @escaping (DailyFeeDetail?) -> (),
                                 failure: @escaping (Message) -> ()) {
        
        let parameters: [String: Any] = ["order_id": orderId]
        
        Base<DailyFeeDetail>.request(URIString: "user/query_daily_fee_detail", parameters: parameters, success: { data in
            success(data)
        }) { error, data in
            failure(error)
        }
    }
    
}
